home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Games / NetHack 3.1.3 / source / src / sp_lev.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-01  |  58.7 KB  |  2,508 lines  |  [TEXT/R*ch]

  1. /*    SCCS Id: @(#)sp_lev.c    3.1    93/06/29    */
  2. /*    Copyright (c) 1989 by Jean-Christophe Collet */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. /*
  6.  * This file contains the various functions that are related to the special
  7.  * levels.
  8.  * It contains also the special level loader.
  9.  *
  10.  */
  11.  
  12. #include "hack.h"
  13. /*#define DEBUG     /* uncomment to enable code debugging */
  14.  
  15. #ifdef DEBUG
  16. # ifdef WIZARD
  17. #define debugpline    if (wizard) pline
  18. # else
  19. #define debugpline    pline
  20. # endif
  21. #endif
  22.  
  23. #include "sp_lev.h"
  24. #include "rect.h"
  25.  
  26. extern void FDECL(mkmap, (lev_init *));
  27.  
  28. static void FDECL(get_room_loc, (schar *, schar *, struct mkroom *));
  29. static void FDECL(get_free_room_loc, (schar *, schar *, struct mkroom *));
  30. static void FDECL(create_trap, (trap *, struct mkroom *));
  31. static void FDECL(create_monster, (monster *, struct mkroom *));
  32. static void FDECL(create_object, (object *, struct mkroom *));
  33. static void FDECL(create_stairs, (stair *, struct mkroom *));
  34. static void FDECL(create_altar, (altar *, struct mkroom *));
  35. static void FDECL(create_gold, (gold *, struct mkroom *));
  36. static void FDECL(create_feature, (int,int,struct mkroom *,int));
  37. static boolean FDECL(search_door, (struct mkroom *, xchar *, xchar *,
  38.                     XCHAR_P, int));
  39. static void NDECL(fix_stair_rooms);
  40. static void FDECL(create_corridor, (corridor *));
  41.  
  42. static boolean FDECL(create_subroom, (struct mkroom *, XCHAR_P, XCHAR_P,
  43.                     XCHAR_P, XCHAR_P, XCHAR_P, XCHAR_P));
  44.  
  45. #if (defined(MICRO) && !defined(AMIGA)) || defined(THINK_C)
  46. # define RDMODE "rb"
  47. #else
  48. # define RDMODE "r"
  49. #endif
  50.  
  51. #define LEFT    1
  52. #define H_LEFT    2
  53. #define CENTER    3
  54. #define H_RIGHT    4
  55. #define RIGHT    5
  56.  
  57. #define TOP    1
  58. #define BOTTOM    5
  59.  
  60. #define sq(x) ((x)*(x))
  61.  
  62. #define XLIM    4
  63. #define YLIM    3
  64.  
  65. #define Fread    (void)fread
  66. #define New(type)        (type *) alloc(sizeof(type))
  67. #define NewTab(type, size)    (type **) alloc(sizeof(type *) * size)
  68. #define Free(ptr)        if(ptr) free((genericptr_t) (ptr))
  69.  
  70. static NEARDATA walk walklist[50];
  71. extern int min_rx, max_rx, min_ry, max_ry; /* from mkmap.c */
  72.  
  73. static char Map[COLNO][ROWNO];
  74. static char robjects[10], rloc_x[10], rloc_y[10], rmonst[10];
  75. static aligntyp    ralign[3] = { AM_CHAOTIC, AM_NEUTRAL, AM_LAWFUL };
  76. static NEARDATA xchar xstart, ystart;
  77. static NEARDATA char xsize, ysize;
  78.  
  79. static void FDECL(set_wall_property, (XCHAR_P,XCHAR_P,XCHAR_P,XCHAR_P,int));
  80. static int NDECL(rnddoor);
  81. static int NDECL(rndtrap);
  82. static void FDECL(get_location, (schar *,schar *,int));
  83. static void FDECL(sp_lev_shuffle, (char *,char *,int));
  84. static void FDECL(light_region, (region *));
  85. static void FDECL(load_common_data, (FILE *,int));
  86. static boolean FDECL(load_rooms, (FILE *));
  87. static void FDECL(maze1xy, (coord *));
  88. static boolean FDECL(load_maze, (FILE *));
  89. static void FDECL(create_door, (room_door *, struct mkroom *));
  90. static void FDECL(free_rooms,(room **, int));
  91. static void FDECL(build_room, (room *, room*));
  92.  
  93. char *lev_message = 0;
  94. lev_region *lregions = 0;
  95. int num_lregions = 0;
  96. lev_init init_lev;
  97.  
  98. /*
  99.  * Make walls of the area (x1, y1, x2, y2) non diggable/non passwall-able
  100.  */
  101.  
  102. static void
  103. set_wall_property(x1,y1,x2,y2, prop)
  104. xchar x1, y1, x2, y2;
  105. int prop;
  106. {
  107.     register xchar x, y;
  108.  
  109.     for(y = y1; y <= y2; y++)
  110.         for(x = x1; x <= x2; x++)
  111.         if(IS_STWALL(levl[x][y].typ))
  112.             levl[x][y].diggable |= prop;
  113. }
  114.  
  115. /*
  116.  * Choose randomly the state (nodoor, open, closed or locked) for a door
  117.  */
  118.  
  119. static int
  120. rnddoor()
  121. {
  122.     int i;
  123.     
  124.     i = 1 << rn2(5);
  125.     i >>= 1;
  126.     return i;
  127. }
  128.  
  129. /* 
  130.  * Select a random trap
  131.  */
  132.  
  133. static int
  134. rndtrap()
  135. {
  136.     int    rtrap, no_tdoor = !Can_dig_down(&u.uz);
  137.     do {
  138.         rtrap = rnd(TRAPNUM-1);
  139.     } while (rtrap == MAGIC_PORTAL || (no_tdoor && rtrap == TRAPDOOR));
  140.     return(rtrap);
  141. }
  142.  
  143. /* 
  144.  * Coordinates in special level files are handled specially:
  145.  *
  146.  *    if x or y is -11, we generate a random coordinate.
  147.  *    if x or y is between -1 and -10, we read one from the corresponding
  148.  *    register (x0, x1, ... x9).
  149.  *    if x or y is nonnegative, we convert it from relative to the local map
  150.  *    to global coordinates.
  151.  *    The "humidity" flag is used to insure that engravings aren't
  152.  *    created underwater, or eels on dry land.
  153.  */
  154. #define DRY    0x1
  155. #define WET    0x2
  156.  
  157. static boolean FDECL(is_ok_location, (SCHAR_P, SCHAR_P, int));
  158.  
  159. static void
  160. get_location(x, y, humidity)
  161. schar *x, *y;
  162. int humidity;
  163. {
  164.     int cpt = 0;
  165.  
  166.     if (*x >= 0) {            /* normal locations */
  167.         *x += xstart;
  168.         *y += ystart;
  169.     } else if (*x > -11) {        /* special locations */
  170.         *y = ystart + rloc_y[ - *y - 1];
  171.         *x = xstart + rloc_x[ - *x - 1];
  172.     } else {            /* random location */
  173.         do {
  174.         *x = xstart + rn2((int)xsize);
  175.         *y = ystart + rn2((int)ysize);
  176.         if (is_ok_location(*x,*y,humidity)) break;
  177.         } while (++cpt < 100);
  178.         if (cpt >= 100) {
  179.         register int xx, yy;
  180.         /* last try */
  181.         for (xx = 0; xx < xsize; xx++)
  182.             for (yy = 0; yy < ysize; yy++) {
  183.             *x = xstart + xx;
  184.             *y = ystart + yy;
  185.             if (is_ok_location(*x,*y,humidity)) goto found_it;
  186.             }
  187.         panic("get_location:  can't find a place!");
  188.         }
  189.     }
  190. found_it:;
  191.  
  192.     if (*x <= 0 || *x >= COLNO || *y < 0 || *y >= ROWNO) {
  193.         impossible("get_location:  (%d,%d) out of bounds", *x, *y);
  194.         *x = x_maze_max; *y = y_maze_max;
  195.     }
  196. }
  197.  
  198. static boolean
  199. is_ok_location(x, y, humidity)
  200. register schar x, y;
  201. register int humidity;
  202. {
  203.     register int typ;
  204.     register boolean okplace = FALSE;
  205.  
  206.     if (humidity & DRY) {
  207.         typ = levl[x][y].typ;
  208.         okplace = (typ == ROOM || typ == AIR ||
  209.             typ == CLOUD || typ == CORR);
  210.     }
  211.     if (humidity & WET) {
  212.         if (is_pool(x,y) || is_lava(x,y))
  213.         okplace = TRUE;
  214.     }
  215.     return okplace;
  216. }
  217.  
  218. /*
  219.  * Shuffle the registers for locations, objects or monsters
  220.  */
  221.  
  222. static void
  223. sp_lev_shuffle(list1, list2, n)
  224. char list1[], list2[];
  225. int n;
  226. {
  227.     register int i, j;
  228.     register char k;
  229.  
  230.     for (i = n - 1; i > 0; i--) {
  231.         if ((j = rn2(i + 1)) == i) continue;
  232.         k = list1[j];
  233.         list1[j] = list1[i];
  234.         list1[i] = k;
  235.         if (list2) {
  236.             k = list2[j];
  237.             list2[j] = list2[i];
  238.             list2[i] = k;
  239.         }
  240.     }
  241. }
  242.  
  243. /* 
  244.  * Get a relative position inside a room.
  245.  * negative values for x or y means RANDOM!
  246.  */
  247.  
  248. static void
  249. get_room_loc(x,y, croom)
  250. schar        *x, *y;
  251. struct mkroom    *croom;
  252. {
  253.     coord c;
  254.  
  255.     if (*x <0 && *y <0) {
  256.         if (somexy(croom, &c)) {
  257.             *x = c.x;
  258.             *y = c.y;
  259.         } else
  260.             panic("get_room_loc : can't find a place!");
  261.     } else {
  262.         if (*x < 0)
  263.             *x = rn2(croom->hx - croom->lx + 1);
  264.         if (*y < 0)
  265.             *y = rn2(croom->hy - croom->ly + 1);
  266.         *x += croom->lx;
  267.         *y += croom->ly;
  268.     }
  269. }
  270.  
  271. /* 
  272.  * Get a relative position inside a room.
  273.  * negative values for x or y means RANDOM!
  274.  */
  275.  
  276. static void
  277. get_free_room_loc(x,y, croom)
  278. schar        *x, *y;
  279. struct mkroom    *croom;
  280. {
  281.     schar try_x, try_y;
  282.     register int trycnt = 0;
  283.  
  284.     do {
  285.         try_x = *x,  try_y = *y;
  286.         get_room_loc(&try_x, &try_y, croom);
  287.     } while (levl[try_x][try_y].typ != ROOM && ++trycnt <= 100);
  288.  
  289.     if (trycnt > 100)
  290.         panic("get_free_room_loc:  can't find a place!");
  291.     *x = try_x,  *y = try_y;
  292. }
  293.  
  294. boolean
  295. check_room(lowx, ddx, lowy, ddy, vault)
  296. xchar *lowx, *ddx, *lowy, *ddy;
  297. boolean vault;
  298. {
  299.     register int x,y,hix = *lowx + *ddx, hiy = *lowy + *ddy;
  300.     register struct rm *lev;
  301.     int xlim, ylim, ymax;
  302.  
  303.     xlim = XLIM + (vault ? 1 : 0);
  304.     ylim = YLIM + (vault ? 1 : 0);
  305.     
  306.     if (*lowx < 3)        *lowx = 3;
  307.     if (*lowy < 2)        *lowy = 2;
  308.     if (hix > COLNO-3)    hix = COLNO-3;
  309.     if (hiy > ROWNO-3)    hiy = ROWNO-3;
  310. chk:
  311.     if (hix <= *lowx || hiy <= *lowy)    return FALSE;
  312.  
  313.     /* check area around room (and make room smaller if necessary) */
  314.     for (x = *lowx - xlim; x<= hix + xlim; x++) {
  315.         if(x <= 0 || x >= COLNO) continue;
  316.         y = *lowy - ylim;    ymax = hiy + ylim;
  317.         if(y < 0) y = 0;
  318.         if(ymax >= ROWNO) ymax = (ROWNO-1);
  319.         lev = &levl[x][y];
  320.         for (; y <= ymax; y++) {
  321.             if (lev++->typ) {
  322. #ifdef DEBUG
  323.                 if(!vault)
  324.                     debugpline("strange area [%d,%d] in check_room.",x,y);
  325. #endif
  326.                 if (!rn2(3))    return FALSE;
  327.                 if (x < *lowx)
  328.                     *lowx = x + xlim + 1;
  329.                 else
  330.                     hix = x - xlim - 1;
  331.                 if (y < *lowy)
  332.                     *lowy = y + ylim + 1;
  333.                 else
  334.                     hiy = y - ylim - 1;
  335.                 goto chk;
  336.             }
  337.         }
  338.     }
  339.     *ddx = hix - *lowx;
  340.     *ddy = hiy - *lowy;
  341.     return TRUE;
  342. }
  343.  
  344. /* 
  345.  * Create a new room.
  346.  * This is still very incomplete...
  347.  */
  348.  
  349. boolean
  350. create_room(x,y,w,h,xal,yal,rtype,rlit)
  351. xchar    x,y;
  352. xchar    w,h;
  353. xchar    xal,yal;
  354. xchar    rtype, rlit;
  355. {
  356.     xchar    xabs, yabs;
  357.     int    wtmp, htmp, xaltmp, yaltmp, xtmp, ytmp;
  358.     NhRect    *r1 = 0, r2;
  359.     int    trycnt = 0;
  360.     boolean    vault = FALSE;
  361.     int    xlim = XLIM, ylim = YLIM;
  362.  
  363.     if (rtype == -1)    /* Is the type random ? */
  364.         rtype = OROOM;
  365.  
  366.     if (rtype == VAULT) {
  367.         vault = TRUE;
  368.         xlim++;
  369.         ylim++;
  370.     }
  371.  
  372.     /* on low levels the room is lit (usually) */
  373.     /* some other rooms may require lighting */
  374.  
  375.     /* is light state random ? */
  376.     if (rlit == -1)
  377.         rlit = (rnd(1+abs(depth(&u.uz))) < 11 && rn2(77)) ? TRUE : FALSE;
  378.  
  379.     /*
  380.      * Here we will try to create a room. If some parameters are
  381.      * random we are willing to make several try before we give
  382.      * it up.
  383.      */
  384.     do {
  385.         xchar xborder, yborder;
  386.         wtmp = w; htmp = h;
  387.         xtmp = x; ytmp = y;
  388.         xaltmp = xal; yaltmp = yal;
  389.  
  390.         /* First case : a totaly random room */
  391.  
  392.         if((xtmp < 0 && ytmp <0 && wtmp < 0 && xaltmp < 0 &&
  393.            yaltmp < 0) || vault) {
  394.             xchar hx, hy, lx, ly, dx, dy;
  395.             r1 = rnd_rect(); /* Get a random rectangle */
  396.  
  397.             if (!r1) { /* No more free rectangles ! */
  398. #ifdef DEBUG
  399.                 debugpline("No more rects...");
  400. #endif
  401.                 return FALSE;
  402.             }
  403.             hx = r1->hx;
  404.             hy = r1->hy;
  405.             lx = r1->lx;
  406.             ly = r1->ly;
  407.             if (vault)
  408.                 dx = dy = 1;
  409.             else {
  410.                 dx = 2 + rn2((hx-lx > 28) ? 12 : 8);
  411.                 dy = 2 + rn2(4);
  412.                 if(dx*dy > 50)
  413.                     dy = 50/dx;
  414.             }
  415.             xborder = (lx > 0 && hx < COLNO -1) ? 2*xlim : xlim+1;
  416.             yborder = (ly > 0 && hy < ROWNO -1) ? 2*ylim : ylim+1;
  417.             if(hx-lx < dx + 3 + xborder ||
  418.                hy-ly < dy + 3 + yborder) {
  419.                 r1 = 0;
  420.                 continue;
  421.             }
  422.             xabs = lx + (lx > 0 ? xlim : 3)
  423.                 + rn2(hx - (lx>0?lx : 3) - dx - xborder + 1);
  424.             yabs = ly + (ly > 0 ? ylim : 2) 
  425.                 + rn2(hy - (ly>0?ly : 2) - dy - yborder + 1);
  426.             if (ly == 0 && hy >= (ROWNO-1) &&
  427.                 (!nroom || !rn2(nroom)) && (yabs+dy > ROWNO/2)) {
  428.                 yabs = rn1(3, 2);
  429.                 if(nroom < 4 && dy>1) dy--;
  430.                 }
  431.             if (!check_room(&xabs, &dx, &yabs, &dy, vault)) {
  432.                 r1 = 0;
  433.                 continue;
  434.             }
  435.             wtmp = dx+1;
  436.             htmp = dy+1;
  437.             r2.lx = xabs-1; r2.ly = yabs-1;
  438.             r2.hx = xabs + wtmp;
  439.             r2.hy = yabs + htmp;
  440.         } else {    /* Only some parameters are random */
  441.             int rndpos = 0;
  442.             if (xtmp < 0 && ytmp < 0) { /* Position is RANDOM */
  443.                 xtmp = rnd(5);
  444.                 ytmp = rnd(5);
  445.                 rndpos = 1;
  446.             }
  447.             if (wtmp < 0 || htmp < 0) { /* Size is RANDOM */
  448.                 wtmp = rn1(15, 3);
  449.                 htmp = rn1(8, 2);
  450.             }
  451.             if (xaltmp == -1) /* Horizontal alignment is RANDOM */
  452.                 xaltmp = rnd(3);
  453.             if (yaltmp == -1) /* Vertical alignment is RANDOM */
  454.                 yaltmp = rnd(3);
  455.  
  456.             /* Try to generate real (absolute) coordinates here! */
  457.             
  458.             xabs = (((xtmp-1) * COLNO) / 5) + 1;
  459.             yabs = (((ytmp-1) * ROWNO) / 5) + 1;
  460.             switch (xaltmp) {
  461.                   case LEFT:
  462.                 break;
  463.                   case RIGHT:
  464.                 xabs += (COLNO / 5) - wtmp;
  465.                 break;
  466.                   case CENTER:
  467.                 xabs += ((COLNO / 5) - wtmp) / 2;
  468.                 break;
  469.             }
  470.             switch (yaltmp) {
  471.                   case TOP:
  472.                 break;
  473.                   case BOTTOM:
  474.                 yabs += (ROWNO / 5) - htmp;
  475.                 break;
  476.                   case CENTER:
  477.                 yabs += ((ROWNO / 5) - htmp) / 2;
  478.                 break;
  479.             }
  480.             
  481.             if (xabs + wtmp - 1 > COLNO - 2) 
  482.                 xabs = COLNO - wtmp - 3;
  483.             
  484.             if (xabs < 2)
  485.                 xabs = 2;
  486.             
  487.             if (yabs + htmp - 1> ROWNO - 2)
  488.                 yabs = ROWNO - htmp - 3;
  489.  
  490.             if (yabs < 2)
  491.                 yabs = 2;
  492.             /* Try to find a rectangle that fit our room ! */
  493.  
  494.             r2.lx = xabs-1; r2.ly = yabs-1;
  495.             r2.hx = xabs + wtmp + rndpos;
  496.             r2.hy = yabs + htmp + rndpos;
  497.             r1 = get_rect(&r2);
  498.         }
  499.     } while (++trycnt <= 100 && !r1);
  500.     if (!r1) {    /* creation of room failed ? */
  501.         return FALSE;
  502.     }
  503.     split_rects(r1, &r2);
  504.  
  505.     if (!vault) {
  506.         smeq[nroom] = nroom;
  507.         add_room(xabs, yabs, xabs+wtmp-1, yabs+htmp-1,
  508.              rlit, rtype, FALSE);
  509.     } else {
  510.         rooms[nroom].lx = xabs;
  511.         rooms[nroom].ly = yabs;
  512.     }
  513.     return TRUE;
  514. }
  515.  
  516. /* 
  517.  * Create a subroom in room proom at pos x,y with width w & height h.
  518.  * x & y are relative to the parent room.
  519.  */
  520.  
  521. static boolean
  522. create_subroom(proom, x, y, w,  h, rtype, rlit)
  523. struct mkroom *proom;
  524. xchar x,y;
  525. xchar w,h;
  526. xchar rtype, rlit;
  527. {
  528.     xchar width, height;
  529.  
  530.     width = proom->hx - proom->lx + 1;
  531.     height = proom->hy - proom->ly + 1;
  532.  
  533.     /* There is a minimum size for the parent room */
  534.     if (width < 4 || height < 4)
  535.         return FALSE;
  536.  
  537.     /* Check for random position, size, etc... */
  538.  
  539.     if (w == -1)
  540.         w = rnd(width - 3);
  541.     if (h == -1)
  542.         h = rnd(height - 3);
  543.     if (x == -1)
  544.         x = rnd(width - w - 1) - 1;
  545.     if (y == -1)
  546.         y = rnd(height - h - 1) - 1;
  547.     if (x == 1)
  548.         x = 0;
  549.     if (y == 1)
  550.         y = 0;
  551.     if ((x + w + 1) == width)
  552.         x++;
  553.     if ((y + h + 1) == height)
  554.         y++;
  555.     if (rtype == -1)
  556.         rtype = OROOM;
  557.     if (rlit == -1)
  558.         rlit = (rnd(1+abs(depth(&u.uz))) < 11 && rn2(77)) ? TRUE : FALSE;
  559.     add_subroom(proom, proom->lx + x, proom->ly + y, 
  560.             proom->lx + x + w - 1, proom->ly + y + h - 1,
  561.             rlit, rtype, FALSE);
  562.     return TRUE;
  563. }
  564.  
  565. /* 
  566.  * Create a new door in a room.
  567.  * It's placed on a wall (north, south, east or west).
  568.  */
  569.  
  570. static void
  571. create_door(dd, broom)
  572. room_door *dd;
  573. struct mkroom *broom;
  574. {
  575.     int    x, y;
  576.     int    trycnt = 0;
  577.  
  578.     if (dd->secret == -1)
  579.         dd->secret = rn2(2);
  580.  
  581.     if (dd->mask == -1) {
  582.         /* is it a locked door, closed, or a doorway? */
  583.         if (!dd->secret) {
  584.             if(!rn2(3)) {
  585.                 if(!rn2(5))
  586.                     dd->mask = D_ISOPEN;
  587.                 else if(!rn2(6))
  588.                     dd->mask = D_LOCKED;
  589.                 else
  590.                     dd->mask = D_CLOSED;
  591.                 if (dd->mask != D_ISOPEN && !rn2(25))
  592.                     dd->mask |= D_TRAPPED;
  593.             } else 
  594.                 dd->mask = D_NODOOR;
  595.         } else {
  596.             if(!rn2(5))    dd->mask = D_LOCKED;
  597.             else        dd->mask = D_CLOSED;
  598.  
  599.             if(!rn2(20)) dd->mask |= D_TRAPPED;
  600.         }
  601.     }
  602.  
  603.     do {
  604.         register int dwall, dpos;
  605.  
  606.         dwall = dd->wall;
  607.         if (dwall == -1)    /* The wall is RANDOM */
  608.             dwall = 1 << rn2(4);
  609.  
  610.         dpos = dd->pos;
  611.         if (dpos == -1)    /* The position is RANDOM */
  612.             dpos = rn2((dwall == W_WEST || dwall == W_EAST) ?
  613.                 (broom->hy - broom->ly) : (broom->hx - broom->lx));
  614.         
  615.         /* Convert wall and pos into an absolute coordinate! */
  616.         
  617.         switch (dwall) {
  618.               case W_NORTH:
  619.             y = broom->ly - 1;
  620.             x = broom->lx + dpos;
  621.             break;
  622.               case W_SOUTH:
  623.             y = broom->hy + 1;
  624.             x = broom->lx + dpos;
  625.             break;
  626.               case W_WEST:
  627.             x = broom->lx - 1;
  628.             y = broom->ly + dpos;
  629.             break;
  630.               case W_EAST:
  631.             x = broom->hx + 1;
  632.             y = broom->ly + dpos;
  633.             break;
  634.               default:
  635.             x = y = 0;
  636.             panic("create_door: No wall for door!");
  637.             break;
  638.         }
  639.         if (okdoor(x,y))
  640.             break;
  641.     } while (++trycnt <= 100);
  642.     if (trycnt > 100) {
  643.         impossible("create_door: Can't find a proper place!");
  644.         return;
  645.     }
  646.     add_door(x,y,broom);
  647.     levl[x][y].typ = (dd->secret ? SDOOR : DOOR);
  648.     levl[x][y].doormask = dd->mask;
  649. }
  650.  
  651. /*
  652.  * Create a secret door in croom on any one of the specified walls.
  653.  */
  654. void
  655. create_secret_door(croom, walls)
  656.     struct mkroom *croom;
  657.     xchar walls; /* any of W_NORTH | W_SOUTH | W_EAST | W_WEST (or W_ANY) */
  658. {
  659.     xchar sx, sy; /* location of the secret door */
  660.     int count;
  661.  
  662.     for(count = 0; count < 100; count++) {
  663.     sx = rn1(croom->hx - croom->lx + 1, croom->lx);
  664.     sy = rn1(croom->hy - croom->ly + 1, croom->ly);
  665.  
  666.     switch(rn2(4)) {
  667.     case 0:  /* top */
  668.         if(!(walls & W_NORTH)) continue;
  669.         sy = croom->ly-1; break;
  670.     case 1: /* bottom */
  671.         if(!(walls & W_SOUTH)) continue;
  672.         sy = croom->hy+1; break;
  673.     case 2: /* left */
  674.         if(!(walls & W_EAST)) continue;
  675.         sx = croom->lx-1; break;
  676.     case 3: /* right */
  677.         if(!(walls & W_WEST)) continue;
  678.         sx = croom->hx+1; break;
  679.     }
  680.  
  681.     if(okdoor(sx,sy)) {
  682.         levl[sx][sy].typ = SDOOR;
  683.         levl[sx][sy].doormask = D_CLOSED;
  684.         add_door(sx,sy,croom);
  685.         return;
  686.     }
  687.     }
  688.  
  689.     impossible("couldn't create secret door on any walls 0x%x", walls);
  690. }
  691.  
  692. /* 
  693.  * Create a trap in a room.
  694.  */
  695.  
  696. static void
  697. create_trap(t,croom)
  698. trap    *t;
  699. struct mkroom    *croom;
  700. {
  701.     schar        x,y;
  702.     coord tm;
  703.  
  704.     x = t->x;
  705.     y = t->y;
  706.     if (croom)
  707.         get_free_room_loc(&x, &y, croom);
  708.     else
  709.         get_location(&x, &y, DRY);
  710.  
  711.     tm.x = x;
  712.     tm.y = y;
  713.  
  714.     mktrap(t->type, 1, (struct mkroom*) 0, &tm);
  715. }
  716.  
  717. /* 
  718.  * Create a monster in a room.
  719.  */
  720.  
  721. static void
  722. create_monster(m,croom)
  723. monster    *m;
  724. struct mkroom    *croom;
  725. {
  726.     struct monst    *mtmp;
  727.     schar        x,y;
  728.     char        class;
  729.     aligntyp    amask;
  730.     struct permonst *pm;
  731.  
  732.     if (m->class >= 0) {
  733.         class = (char) def_char_to_monclass((char)m->class);
  734.         if (class == MAXMCLASSES) goto bad_class;
  735.     } else if (m->class > -11) {
  736.         class = (char) def_char_to_monclass(rmonst[- m->class - 1]);
  737.         if (class == MAXMCLASSES) {
  738. bad_class:
  739.         panic("create_monster: unknown monster class '%c'", m->class);
  740.         }
  741.     } else
  742.         class = 0;
  743.  
  744.     amask = (m->align <= -11) ? induced_align(80) :
  745.         (m->align < 0 ? ralign[-m->align-1] : m->align);
  746.  
  747.     if (!class)
  748.         pm = (struct permonst *) 0;
  749.     else if (m->id != -1) {
  750. #ifdef MULDGN
  751.         if(pl_character[0] == 'E' && m->id == PM_EARENDIL)
  752.         m->id += flags.female;
  753. #endif
  754.         pm = &mons[m->id];
  755.     } else {
  756.         pm = mkclass(class,G_NOGEN);
  757.         /* if we can't get class for a specific monster type,
  758.            it means, that it's extinct, genocided, or unique,
  759.            and shouldn't be created. */
  760.         if (!pm) return;
  761.     }
  762.  
  763.     x = m->x;
  764.     y = m->y;
  765.     if (croom)
  766.         get_room_loc(&x, &y, croom);
  767.     else {
  768.         if (!pm || !is_swimmer(pm))
  769.         get_location(&x, &y, DRY);
  770.         else if (pm->mlet == S_EEL)
  771.         get_location(&x, &y, WET);
  772.         else
  773.         get_location(&x, &y, DRY|WET);
  774.     }
  775.  
  776.  
  777.     if(m->align != -12)
  778.         mtmp = mk_roamer(pm, Amask2align(amask), x, y, m->peaceful);
  779.     else if(PM_ARCHEOLOGIST <= m->id && m->id <= PM_WIZARD)
  780.              mtmp = mk_mplayer(pm, x, y, FALSE);
  781.     else mtmp = makemon(pm, x, y);
  782.  
  783.     if (mtmp) {
  784.         /* handle specific attributes for some special monsters */
  785.         if (m->name) mtmp = christen_monst(mtmp, m->name);
  786.  
  787.         /*
  788.          * This is currently hardwired for mimics only.  It should
  789.          * eventually be expanded.
  790.          */
  791.         if (m->appear_as && mtmp->data->mlet == S_MIMIC) {
  792.         int i;
  793.  
  794.         switch (m->appear) {
  795.             case M_AP_NOTHING:
  796.             impossible(
  797.         "create_monster: mon has an appearance, \"%s\", but no type",
  798.                 m->appear_as);
  799.             break;
  800.  
  801.             case M_AP_FURNITURE:
  802.             for (i = 0; i < MAXPCHARS; i++)
  803.                 if (!strcmp(defsyms[i].explanation, m->appear_as))
  804.                 break;
  805.             if (i == MAXPCHARS) {
  806.                 impossible(
  807.                 "create_monster: can't find feature \"%s\"",
  808.                     m->appear_as);
  809.             } else {
  810.                 mtmp->m_ap_type = M_AP_FURNITURE;
  811.                 mtmp->mappearance = i;
  812.             }
  813.             break;
  814.  
  815.             case M_AP_OBJECT:
  816.             for (i = 0; i < NROFOBJECTS; i++)
  817.                 if (!strcmp(OBJ_NAME(objects[i]), m->appear_as))
  818.                 break;
  819.             if (i == NROFOBJECTS) {
  820.                 impossible(
  821.                 "create_monster: can't find object \"%s\"",
  822.                     m->appear_as);
  823.             } else {
  824.                 mtmp->m_ap_type = M_AP_OBJECT;
  825.                 mtmp->mappearance = i;
  826.             }
  827.             break;
  828.  
  829.             case M_AP_MONSTER:
  830.             /* note: mimics don't appear as monsters! */
  831.             /*      (but chameleons can :-)      */
  832.             default:
  833.             impossible(
  834.         "create_monster: unimplemented mon appear type [%d,\"%s\"]",
  835.                 m->appear, m->appear_as);
  836.             break;
  837.         }
  838.         if (does_block(x, y, &levl[x][y]))
  839.             block_point(x, y);
  840.         }
  841.  
  842.         if (m->peaceful >= 0) {
  843.         mtmp->mpeaceful = m->peaceful;
  844.         /* changed mpeaceful again; have to reset malign */
  845.         set_malign(mtmp);
  846.         }
  847.         if (m->asleep >= 0) {
  848. #ifdef UNIXPC
  849.         /* optimizer bug strikes again */
  850.         if (m->asleep)
  851.             mtmp->msleep = TRUE;
  852.         else
  853.             mtmp->msleep = FALSE;
  854. #else
  855.         mtmp->msleep = m->asleep;
  856. #endif
  857.         }
  858.     }
  859. }
  860.  
  861. /* 
  862.  * Create an object in a room.
  863.  */
  864.  
  865. static void
  866. create_object(o,croom)
  867. object    *o;
  868. struct mkroom    *croom;
  869. {
  870.     struct obj    *otmp;
  871.     schar    x,y;
  872.     char    c;
  873.  
  874.     x = o->x; y = o->y;
  875.     if (croom)
  876.         get_room_loc(&x, &y, croom);
  877.     else
  878.         get_location(&x, &y, DRY);
  879.  
  880.     if (o->class >= 0)
  881.         c = o->class;
  882.     else if (o->class > -11)
  883.         c = robjects[ -(o->class+1)];
  884.     else
  885.         c = 0;
  886.  
  887.     if (!c)
  888.         otmp = mkobj_at(RANDOM_CLASS, x, y, TRUE);
  889.     else if (o->id != -1)
  890.         otmp = mksobj_at(o->id, x, y, TRUE);
  891.     else {
  892.         /*
  893.          * The special levels are compiled with the default "text" object
  894.          * class characters.  We must convert them to the internal format.
  895.          */
  896.         char oclass = (char) def_char_to_objclass(c);
  897.  
  898.         if (oclass == MAXOCLASSES)
  899.         panic("create_object:  unexpected object class '%c'",c);
  900.         otmp = mkobj_at(oclass, x, y, TRUE);
  901.     }
  902.  
  903.     if (o->spe != -127)    /* That means NOT RANDOM! */
  904.         otmp->spe = o->spe;
  905.  
  906.     switch (o->curse_state) {
  907.           case 1:    bless(otmp); break; /* BLESSED */
  908.           case 2:    unbless(otmp); uncurse(otmp); break; /* uncursed */
  909.           case 3:    curse(otmp); break; /* CURSED */
  910.           default:    break;    /* Otherwise it's random and we're happy
  911.                  * with what mkobj gave us! */
  912.     }
  913.  
  914.     /*     corpsenm is "empty" if -1, random if -2, otherwise specific */
  915.     if (o->corpsenm == -2) otmp->corpsenm = rndmonnum();
  916.     else if (o->corpsenm != -1) otmp->corpsenm = o->corpsenm;
  917.  
  918.     if (o->name) {        /* Give a name to that object */
  919.         /* Note: oname() is safe since otmp is first in chains */
  920.         otmp = oname(otmp, o->name, 0);
  921.         fobj = otmp;
  922.         level.objects[x][y] = otmp;
  923.     }
  924.     stackobj(otmp);
  925. }
  926.  
  927. /* 
  928.  * Create stairs in a room.
  929.  * 
  930.  */
  931.  
  932. static void
  933. create_stairs(s,croom)
  934. stair    *s;
  935. struct mkroom    *croom;
  936. {
  937.     schar        x,y;
  938.  
  939.     x = s->x; y = s->y;
  940.     get_free_room_loc(&x, &y, croom);
  941.     mkstairs(x,y,(char)s->up, croom);
  942. }
  943.  
  944. /* 
  945.  * Create an altar in a room.
  946.  */
  947.  
  948. static void
  949. create_altar(a, croom)
  950.     altar        *a;
  951.     struct mkroom    *croom;
  952. {
  953.     schar        sproom,x,y;
  954.     aligntyp    amask;
  955.     boolean        croom_is_temple = TRUE;
  956.  
  957.     x = a->x; y = a->y;
  958.  
  959.     if (croom) {
  960.         get_free_room_loc(&x, &y, croom);
  961.         if (croom->rtype != TEMPLE)
  962.         croom_is_temple = FALSE;
  963.     } else {
  964.         get_location(&x, &y, DRY);
  965.         if ((sproom = (schar) *in_rooms(x, y, TEMPLE)) != 0)
  966.         croom = &rooms[sproom - ROOMOFFSET];
  967.         else
  968.         croom_is_temple = FALSE;
  969.     }
  970.  
  971.     a->x = x;
  972.     a->y = y;
  973.  
  974.     /* Is the alignment random ?
  975.      * If so, it's an 80% chance that the altar will be co-aligned.
  976.      *
  977.      * The alignment is encoded as amask values instead of alignment
  978.      * values to avoid conflicting with the rest of the encoding,
  979.      * shared by many other parts of the special level code.
  980.      */
  981.  
  982.     amask = (a->align == -11) ? induced_align(80) :
  983.         (a->align < 0 ? ralign[-a->align-1] : a->align);
  984.  
  985.     levl[x][y].typ = ALTAR;
  986.     levl[x][y].altarmask = amask;
  987.  
  988.     if (a->shrine == -11) a->shrine = rn2(1);  /* handle random case */
  989.  
  990.     if (!croom_is_temple || !a->shrine) return;
  991.  
  992.     if (a->shrine) {    /* Is it a shrine  or sanctum? */
  993.         priestini(&u.uz, croom, x, y, (a->shrine > 1));
  994.         levl[x][y].altarmask |= AM_SHRINE;
  995.         level.flags.has_temple = TRUE;
  996.     }
  997. }
  998.  
  999. /* 
  1000.  * Create a gold pile in a room.
  1001.  */
  1002.  
  1003. static void
  1004. create_gold(g,croom)
  1005. gold *g;
  1006. struct mkroom    *croom;
  1007. {
  1008.     schar        x,y;
  1009.  
  1010.     x = g->x; y= g->y;
  1011.     if (croom)
  1012.         get_room_loc(&x, &y, croom);
  1013.     else
  1014.         get_location(&x, &y, DRY);
  1015.  
  1016.     if (g->amount == -1)
  1017.         g->amount = rnd(200);
  1018.     mkgold((long) g->amount, x, y);
  1019. }
  1020.  
  1021. /* 
  1022.  * Create a feature (e.g a fountain) in a room.
  1023.  */
  1024.  
  1025. static void
  1026. create_feature(fx, fy, croom, typ)
  1027. int        fx, fy;
  1028. struct mkroom    *croom;
  1029. int        typ;
  1030. {
  1031.     schar        x,y;
  1032.     int        trycnt = 0;
  1033.  
  1034.     x = fx;  y = fy;
  1035.     if (croom) {
  1036.         if (x < 0 && y < 0)
  1037.         do {
  1038.             x = -1;  y = -1;
  1039.             get_room_loc(&x, &y, croom);
  1040.         } while (++trycnt <= 200 && occupied(x,y));
  1041.         else
  1042.         get_room_loc(&x, &y, croom);
  1043.         if(trycnt > 200)
  1044.         return;
  1045.     } else {
  1046.         get_location(&x, &y, DRY);
  1047.     }
  1048.     levl[x][y].typ = typ;
  1049.     if (typ == FOUNTAIN)
  1050.         level.flags.nfountains++;
  1051.     else if (typ == SINK)
  1052.         level.flags.nsinks++;
  1053. }
  1054.  
  1055. /* 
  1056.  * Search for a door in a room on a specified wall.
  1057.  */
  1058.  
  1059. static boolean
  1060. search_door(croom,x,y,wall,cnt)
  1061. struct mkroom *croom;
  1062. xchar *x, *y;
  1063. xchar wall;
  1064. int cnt;
  1065. {
  1066.     int dx, dy;
  1067.     int xx,yy;
  1068.  
  1069.     switch(wall) {
  1070.           case W_NORTH:
  1071.         dy = 0; dx = 1;
  1072.         xx = croom->lx;
  1073.         yy = croom->hy + 1;
  1074.         break;
  1075.           case W_SOUTH:
  1076.         dy = 0; dx = 1;
  1077.         xx = croom->lx;
  1078.         yy = croom->ly - 1;
  1079.         break;
  1080.           case W_EAST:
  1081.         dy = 1; dx = 0;
  1082.         xx = croom->hx + 1;
  1083.         yy = croom->ly;
  1084.         break;
  1085.           case W_WEST:
  1086.         dy = 1; dx = 0;
  1087.         xx = croom->lx - 1;
  1088.         yy = croom->ly;
  1089.         break;
  1090.           default:
  1091.         dx = dy = xx = yy = 0;
  1092.         panic("search_door: Bad wall!");
  1093.         break;
  1094.     }
  1095.     while (xx <= croom->hx+1 && yy <= croom->hy+1) {
  1096.         if (IS_DOOR(levl[xx][yy].typ) || levl[xx][yy].typ == SDOOR) {
  1097.             *x = xx;
  1098.             *y = yy;
  1099.             if (cnt-- <= 0) 
  1100.                 return TRUE;
  1101.         }
  1102.         xx += dx;
  1103.         yy += dy;
  1104.     }
  1105.     return FALSE;
  1106. }
  1107.  
  1108. /* 
  1109.  * Dig a corridor between two points.
  1110.  */
  1111.  
  1112. boolean
  1113. dig_corridor(org,dest,nxcor,ftyp,btyp)
  1114. coord org, dest;
  1115. boolean nxcor;
  1116. schar ftyp, btyp;
  1117. {
  1118.     register int dx=0, dy=0, dix, diy, cct;
  1119.     register struct rm *crm;
  1120.     register int tx, ty, xx, yy;
  1121.  
  1122.     xx = org.x;  yy = org.y;
  1123.     tx = dest.x; ty = dest.y;
  1124.     if (xx <= 0 || yy <= 0 || tx <= 0 || ty <= 0 ||
  1125.         xx > COLNO-1 || tx > COLNO-1 ||
  1126.         yy > ROWNO-1 || ty > ROWNO-1) {
  1127. #ifdef DEBUG
  1128.         debugpline("dig_corridor: bad coords : (%d,%d) (%d,%d).",
  1129.                xx,yy,tx,ty);
  1130. #endif
  1131.         return FALSE;
  1132.     }
  1133.     if (tx > xx)        dx = 1;
  1134.     else if (ty > yy)    dy = 1;
  1135.     else if (tx < xx)    dx = -1;
  1136.     else            dy = -1;
  1137.     
  1138.     xx -= dx;
  1139.     yy -= dy;
  1140.     cct = 0;
  1141.     while(xx != tx || yy != ty) {
  1142.         /* loop: dig corridor at [xx,yy] and find new [xx,yy] */
  1143.         if(cct++ > 500 || (nxcor && !rn2(35)))
  1144.         return FALSE;
  1145.  
  1146.         xx += dx;
  1147.         yy += dy;
  1148.  
  1149.         if(xx >= COLNO-1 || xx <= 0 || yy <= 0 || yy >= ROWNO-1)
  1150.         return FALSE;        /* impossible */
  1151.  
  1152.         crm = &levl[xx][yy];
  1153.         if(crm->typ == btyp) {
  1154.         if(ftyp != CORR || rn2(100)) {
  1155.             crm->typ = ftyp;
  1156.             if(nxcor && !rn2(50))
  1157.                 (void) mksobj_at(BOULDER, xx, yy, TRUE);
  1158.         } else {
  1159.             crm->typ = SCORR;
  1160.         }
  1161.         } else
  1162.         if(crm->typ != ftyp && crm->typ != SCORR) {
  1163.         /* strange ... */
  1164.         return FALSE;
  1165.         }
  1166.  
  1167.         /* find next corridor position */
  1168.         dix = abs(xx-tx);
  1169.         diy = abs(yy-ty);
  1170.  
  1171.         /* do we have to change direction ? */
  1172.         if(dy && dix > diy) {
  1173.         register int ddx = (xx > tx) ? -1 : 1;
  1174.  
  1175.         crm = &levl[xx+ddx][yy];
  1176.         if(crm->typ == btyp || crm->typ == ftyp || crm->typ == SCORR) {
  1177.             dx = ddx;
  1178.             dy = 0;
  1179.             continue;
  1180.         }
  1181.         } else if(dx && diy > dix) {
  1182.         register int ddy = (yy > ty) ? -1 : 1;
  1183.  
  1184.         crm = &levl[xx][yy+ddy];
  1185.         if(crm->typ == btyp || crm->typ == ftyp || crm->typ == SCORR) {
  1186.             dy = ddy;
  1187.             dx = 0;
  1188.             continue;
  1189.         }
  1190.         }
  1191.  
  1192.         /* continue straight on? */
  1193.         crm = &levl[xx+dx][yy+dy];
  1194.         if(crm->typ == btyp || crm->typ == ftyp || crm->typ == SCORR)
  1195.         continue;
  1196.  
  1197.         /* no, what must we do now?? */
  1198.         if(dx) {
  1199.         dx = 0;
  1200.         dy = (ty < yy) ? -1 : 1;
  1201.         } else {
  1202.         dy = 0;
  1203.         dx = (tx < xx) ? -1 : 1;
  1204.         }
  1205.         crm = &levl[xx+dx][yy+dy];
  1206.         if(crm->typ == btyp || crm->typ == ftyp || crm->typ == SCORR)
  1207.         continue;
  1208.         dy = -dy;
  1209.         dx = -dx;
  1210.     }
  1211.     return TRUE;
  1212. }
  1213.  
  1214. /*
  1215.  * Disgusting hack: since special levels have their rooms filled before
  1216.  * sorting the rooms, we have to re-arrange the speed values upstairs_room
  1217.  * and dnstairs_room after the rooms have been sorted.  On normal levels,
  1218.  * stairs don't get created until _after_ sorting takes place.
  1219.  */
  1220. static void
  1221. fix_stair_rooms()
  1222. {
  1223.     register i;
  1224.     register struct mkroom     *croom;
  1225.  
  1226.     if(xdnstair &&
  1227.        !((dnstairs_room->lx <= xdnstair && xdnstair <= dnstairs_room->hx) &&
  1228.      (dnstairs_room->ly <= ydnstair && ydnstair <= dnstairs_room->hy))) {
  1229.     for(i=0; i < nroom; i++) {
  1230.         croom = &rooms[i];
  1231.         if((croom->lx <= xdnstair && xdnstair <= croom->hx) &&
  1232.            (croom->ly <= ydnstair && ydnstair <= croom->hy)) {
  1233.         dnstairs_room = croom;
  1234.         break;
  1235.         }
  1236.     }
  1237.     if(i == nroom)
  1238.         panic("Couldn't find dnstair room in fix_stair_rooms!");
  1239.     }
  1240.     if(xupstair &&
  1241.        !((upstairs_room->lx <= xupstair && xupstair <= upstairs_room->hx) &&
  1242.      (upstairs_room->ly <= yupstair && yupstair <= upstairs_room->hy))) {
  1243.     for(i=0; i < nroom; i++) {
  1244.         croom = &rooms[i];
  1245.         if((croom->lx <= xupstair && xupstair <= croom->hx) &&
  1246.            (croom->ly <= yupstair && yupstair <= croom->hy)) {
  1247.         upstairs_room = croom;
  1248.         break;
  1249.         }
  1250.     }
  1251.     if(i == nroom)
  1252.         panic("Couldn't find upstair room in fix_stair_rooms!");
  1253.     }
  1254. }
  1255.  
  1256. /* 
  1257.  * Corridors always start from a door. But it can end anywhere...
  1258.  * Basically we search for door coordinates or for endpoints coordinates
  1259.  * (from a distance).
  1260.  */
  1261.  
  1262. static void
  1263. create_corridor(c)
  1264. corridor    *c;
  1265. {
  1266.     coord org, dest;
  1267.  
  1268.     if (c->src.room == -1) {
  1269.         sort_rooms();
  1270.         fix_stair_rooms();
  1271.         makecorridors();
  1272.         return;
  1273.     }
  1274.  
  1275.     if( !search_door(&rooms[c->src.room], &org.x, &org.y, c->src.wall,
  1276.              c->src.door))
  1277.         return;
  1278.  
  1279.     if (c->dest.room != -1) {
  1280.         if(!search_door(&rooms[c->dest.room], &dest.x, &dest.y,
  1281.                 c->dest.wall, c->dest.door))
  1282.             return;
  1283.         switch(c->src.wall) {
  1284.               case W_NORTH: org.y--; break;
  1285.               case W_SOUTH: org.y++; break;
  1286.               case W_WEST:  org.x--; break;
  1287.               case W_EAST:  org.x++; break;
  1288.         }
  1289.         switch(c->dest.wall) {
  1290.               case W_NORTH: dest.y--; break;
  1291.               case W_SOUTH: dest.y++; break;
  1292.               case W_WEST:  dest.x--; break;
  1293.               case W_EAST:  dest.x++; break;
  1294.         }
  1295.         (void) dig_corridor(org, dest, FALSE, CORR, STONE);
  1296.     }
  1297. }
  1298.  
  1299.  
  1300. /* 
  1301.  * Fill a room (shop, zoo, etc...) with appropriate stuff.
  1302.  */
  1303.  
  1304. void
  1305. fill_room(croom, prefilled)
  1306. struct mkroom     *croom;
  1307. boolean prefilled;
  1308. {
  1309.     if (!croom || croom->rtype == OROOM)
  1310.         return;
  1311.  
  1312.     if (!prefilled) {
  1313.         int x,y;
  1314.  
  1315.         /* Shop ? */
  1316.         if (croom->rtype >= SHOPBASE) {
  1317.             stock_room(croom->rtype - SHOPBASE, croom);
  1318.             level.flags.has_shop = TRUE;
  1319.             return;
  1320.         }
  1321.  
  1322.         switch (croom->rtype) {
  1323.         case VAULT:
  1324.             for (x=croom->lx;x<=croom->hx;x++)
  1325.             for (y=croom->ly;y<=croom->hy;y++)
  1326.                 mkgold((long)rn1(abs(depth(&u.uz))*100, 51), x, y);
  1327.             break;
  1328.         case COURT:
  1329.         case ZOO:
  1330.         case BEEHIVE:
  1331.         case MORGUE:
  1332.         case BARRACKS:
  1333.             fill_zoo(croom);
  1334.             break;
  1335.         }
  1336.     }
  1337.     switch (croom->rtype) {
  1338.         case VAULT:
  1339.         level.flags.has_vault = TRUE;
  1340.         break;
  1341.         case ZOO:
  1342.         level.flags.has_zoo = TRUE;
  1343.         break;
  1344.         case COURT:
  1345.         level.flags.has_court = TRUE;
  1346.         break;
  1347.         case MORGUE:
  1348.         level.flags.has_morgue = TRUE;
  1349.         break;
  1350.         case BEEHIVE:
  1351.         level.flags.has_beehive = TRUE;
  1352.         break;
  1353. #ifdef ARMY
  1354.         case BARRACKS:
  1355.         level.flags.has_barracks = TRUE;
  1356.         break;
  1357. #endif
  1358.         case TEMPLE:
  1359.         level.flags.has_temple = TRUE;
  1360.         break;
  1361.         case SWAMP:
  1362.         level.flags.has_swamp = TRUE;
  1363.         break;
  1364.     }
  1365. }
  1366.  
  1367. static void
  1368. free_rooms(ro, n)
  1369. room **ro;
  1370. int n;
  1371. {
  1372.     short j;
  1373.     room *r;
  1374.     
  1375.     while(n--) {
  1376.         r = ro[n];
  1377.         Free(r->name);
  1378.         Free(r->parent);
  1379.         if ((j = r->ndoor) != 0) {
  1380.             while(j--)
  1381.                 Free(r->doors[j]);
  1382.             Free(r->doors);
  1383.         }
  1384.         if ((j = r->ntrap) != 0) {
  1385.             while (j--)
  1386.                 Free(r->traps[j]);
  1387.             Free(r->traps);
  1388.         }
  1389.         if ((j = r->nmonster) != 0) {
  1390.             while (j--) {
  1391.                 Free(r->monsters[j]->name);
  1392.                 Free(r->monsters[j]->appear_as);
  1393.                 Free(r->monsters[j]);
  1394.             }
  1395.             Free(r->monsters);
  1396.         }
  1397.         if ((j = r->nobject) != 0) {
  1398.             while(j--) {
  1399.                 Free(r->objects[j]->name);
  1400.                 Free(r->objects[j]);
  1401.             }
  1402.             Free(r->objects);
  1403.         }
  1404.         if ((j = r->nstair) != 0) {
  1405.             while(j--)
  1406.                 Free(r->stairs[j]);
  1407.             Free(r->stairs);
  1408.         }
  1409.         if ((j = r->naltar) != 0) {
  1410.             while (j--)
  1411.                 Free(r->altars[j]);
  1412.             Free(r->altars);
  1413.         }
  1414.         if ((j = r->ngold) != 0) {
  1415.             while(j--)
  1416.                 Free(r->golds[j]);
  1417.             Free(r->golds);
  1418.         }
  1419.         if ((j = r->nengraving) != 0) {
  1420.             while(j--) {
  1421.                 Free(r->engravings[j]->e.text);
  1422.                 Free(r->engravings[j]);
  1423.             }
  1424.             Free(r->engravings);
  1425.         }
  1426.         if ((j = r->nfountain) != 0) {
  1427.             while(j--)
  1428.                 Free(r->fountains[j]);
  1429.             Free(r->fountains);
  1430.         }
  1431.         if ((j = r->nsink) != 0) {
  1432.             while(j--)
  1433.                 Free(r->sinks[j]);
  1434.             Free(r->sinks);
  1435.         }
  1436.         if ((j = r->npool) != 0) {
  1437.             while(j--)
  1438.                 Free(r->pools[j]);
  1439.             Free(r->pools);
  1440.         }
  1441.         Free(r);
  1442.     }
  1443. }
  1444.  
  1445. static void
  1446. build_room(r, pr)
  1447. room *r, *pr;
  1448. {
  1449.     boolean okroom;
  1450.     struct mkroom    *aroom;
  1451.     short i;
  1452.     xchar rtype = (!r->chance || rn2(100) < r->chance) ? r->rtype : OROOM;
  1453.  
  1454.     if(pr) {
  1455.         aroom = &subrooms[nsubroom];
  1456.         okroom = create_subroom(pr->mkr, r->x, r->y, r->w, r->h,
  1457.                     rtype, r->rlit);
  1458.     } else {
  1459.         aroom = &rooms[nroom];
  1460.         okroom = create_room(r->x, r->y, r->w, r->h, r->xalign,
  1461.                      r->yalign, rtype, r->rlit);
  1462.         r->mkr = aroom;
  1463.     }
  1464.  
  1465.     if (okroom) {
  1466.         /* Create subrooms if necessary... */
  1467.         for(i=0; i < r->nsubroom; i++)
  1468.             build_room(r->subrooms[i], r);
  1469.         /* And now we can fill the room! */
  1470.         
  1471.         /* Priority to the stairs */
  1472.  
  1473.         for(i=0; i <r->nstair; i++)
  1474.             create_stairs(r->stairs[i], aroom);
  1475.  
  1476.         /* Then to the various elements (sinks, etc..) */
  1477.         for(i = 0; i<r->nsink; i++)
  1478.             create_feature(r->sinks[i]->x, r->sinks[i]->y, aroom, SINK);
  1479.         for(i = 0; i<r->npool; i++)
  1480.             create_feature(r->pools[i]->x, r->pools[i]->y, aroom, POOL);
  1481.         for(i = 0; i<r->nfountain; i++)
  1482.             create_feature(r->fountains[i]->x, r->fountains[i]->y,
  1483.                    aroom, FOUNTAIN);
  1484.         for(i = 0; i<r->naltar; i++)
  1485.             create_altar(r->altars[i], aroom);
  1486.         for(i = 0; i<r->ndoor; i++)
  1487.             create_door(r->doors[i], aroom);
  1488.  
  1489.         /* The traps */
  1490.         for(i = 0; i<r->ntrap; i++)
  1491.             create_trap(r->traps[i], aroom);
  1492.  
  1493.         /* The monsters */
  1494.         for(i = 0; i<r->nmonster; i++)
  1495.             create_monster(r->monsters[i], aroom);
  1496.  
  1497.         /* The objects */
  1498.         for(i = 0; i<r->nobject; i++)
  1499.             create_object(r->objects[i], aroom);
  1500.  
  1501.         /* The gold piles */
  1502.         for(i = 0; i<r->ngold; i++)
  1503.             create_gold(r->golds[i], aroom);
  1504.  
  1505.         /* The engravings */
  1506.         for(i = 0; i<r->nengraving; i++) {
  1507.             schar xx, yy;
  1508.  
  1509.             xx = r->engravings[i]->x;
  1510.             yy = r->engravings[i]->y;
  1511.             get_room_loc(&xx, &yy, aroom);
  1512.             make_engr_at(xx, yy, r->engravings[i]->e.text,
  1513.                      0L, r->engravings[i]->etype);
  1514.         }
  1515. #ifdef SPECIALIZATION
  1516.         topologize(aroom,FALSE);        /* set roomno */
  1517. #else
  1518.         topologize(aroom);            /* set roomno */
  1519. #endif
  1520.         /* MRS - 07/04/91 - This is temporary but should result
  1521.          * in proper filling of shops, etc.
  1522.          * DLC - this can fail if corridors are added to this room
  1523.          * at a later point.  Currently no good way to fix this.
  1524.          */
  1525.         if(aroom->rtype != OROOM && r->filled) fill_room(aroom, FALSE);
  1526.     }
  1527. }
  1528.  
  1529. /*
  1530.  * set lighting in a region that will not become a room.
  1531.  */
  1532. static void
  1533. light_region(tmpregion)
  1534.     region  *tmpregion;
  1535. {
  1536.     register boolean litstate = tmpregion->rlit ? 1 : 0;
  1537.     register int hiy = tmpregion->y2;
  1538.     register int x, y;
  1539.     register struct rm *lev;
  1540.     int lowy = tmpregion->y1;
  1541.     int lowx = tmpregion->x1, hix = tmpregion->x2;
  1542.  
  1543.     if(litstate) {
  1544.     /* adjust region size for walls, but only if lighted */
  1545.     lowx = max(lowx-1,1);
  1546.     hix = min(hix+1,COLNO-1);
  1547.     lowy = max(lowy-1,0);
  1548.     hiy = min(hiy+1, ROWNO-1);
  1549.     }
  1550.     for(x = lowx; x <= hix; x++) {
  1551.     lev = &levl[x][lowy];
  1552.     for(y = lowy; y <= hiy; y++)
  1553.         lev++->lit = litstate;
  1554.     }
  1555. }
  1556.  
  1557. /* initialization common to all special levels */
  1558. static void
  1559. load_common_data(fd, typ)
  1560. FILE *fd;
  1561. int typ;
  1562. {
  1563.     uchar    n;
  1564.     long    lev_flags;
  1565.     int    i;
  1566.  
  1567.       {
  1568.     aligntyp atmp;
  1569.     /* shuffle 3 alignments; can't use sp_lev_shuffle() on aligntyp's */
  1570.     i = rn2(3);   atmp=ralign[2]; ralign[2]=ralign[i]; ralign[i]=atmp;
  1571.     if (rn2(2)) { atmp=ralign[1]; ralign[1]=ralign[0]; ralign[0]=atmp; }
  1572.       }
  1573.  
  1574.     level.flags.is_maze_lev = typ == SP_LEV_MAZE;
  1575.  
  1576.     /* free up old level regions */
  1577.     if(num_lregions) {
  1578.         for(i=0; i<num_lregions; i++)
  1579.             if(lregions[i].rname) Free(lregions[i].rname);
  1580.         Free(lregions);
  1581.         num_lregions = 0;
  1582.     }
  1583.     lregions = (lev_region *) 0;
  1584.  
  1585.     /* Read the level initialization data */
  1586.     Fread((genericptr_t) &init_lev, 1, sizeof(lev_init), fd);
  1587.     if(init_lev.init_present) {
  1588.         if(init_lev.lit < 0)
  1589.         init_lev.lit = rn2(2);
  1590.         mkmap(&init_lev);
  1591.     }
  1592.  
  1593.     /* Read the per level flags */
  1594.     Fread((genericptr_t) &lev_flags, 1, sizeof(lev_flags), fd);
  1595.     if (lev_flags & NOTELEPORT)
  1596.         level.flags.noteleport = 1;
  1597.     if (lev_flags & HARDFLOOR)
  1598.         level.flags.hardfloor = 1;
  1599.     if (lev_flags & NOMMAP)
  1600.         level.flags.nommap = 1;
  1601.     if (lev_flags & SHORTSIGHTED)
  1602.         level.flags.shortsighted = 1;
  1603.  
  1604.     /* Read message */
  1605.     Fread((genericptr_t) &n, 1, sizeof(n), fd);
  1606.     if (n) {
  1607.         lev_message = (char *) alloc(n + 1);
  1608.         Fread((genericptr_t) lev_message, 1, (int) n, fd);
  1609.         lev_message[n] = 0;
  1610.     }
  1611. }
  1612.  
  1613. static boolean
  1614. load_rooms(fd)
  1615. FILE *fd;
  1616. {
  1617.     xchar        nrooms;
  1618.     char        n;
  1619.     short        size;
  1620.     corridor    tmpcor;
  1621.     room**        tmproom;
  1622.     int        i, j, ncorr;
  1623.  
  1624.     load_common_data(fd, SP_LEV_ROOMS);
  1625.  
  1626.     Fread((genericptr_t) &n, 1, sizeof(n), fd); /* nrobjects */
  1627.     if (n) {
  1628.         Fread((genericptr_t)robjects, sizeof(*robjects), n, fd);
  1629.         sp_lev_shuffle(robjects, (char *)0, (int)n);
  1630.     }
  1631.  
  1632.     Fread((genericptr_t) &n, 1, sizeof(n), fd); /* nrmonst */
  1633.     if (n) {
  1634.         Fread((genericptr_t)rmonst, sizeof(*rmonst), n, fd);
  1635.         sp_lev_shuffle(rmonst, (char *)0, (int)n);
  1636.     }
  1637.  
  1638.     Fread((genericptr_t) &nrooms, 1, sizeof(nrooms), fd);
  1639.                         /* Number of rooms to read */
  1640.     tmproom = NewTab(room,nrooms);
  1641.     for (i=0;i<nrooms;i++) {
  1642.         room *r;
  1643.  
  1644.         r = tmproom[i] = New(room);
  1645.  
  1646.         /* Let's see if this room has a name */
  1647.         Fread((genericptr_t) &size, 1, sizeof(size), fd);
  1648.         if (size > 0) {    /* Yup, it does! */
  1649.             r->name = (char *) alloc(size + 1);
  1650.             Fread((genericptr_t) r->name, 1, size, fd);
  1651.             r->name[size] = 0;
  1652.         } else
  1653.             r->name = (char *) 0;
  1654.  
  1655.         /* Let's see if this room has a parent */
  1656.         Fread((genericptr_t) &size, 1, sizeof(size), fd);
  1657.         if (size > 0) {    /* Yup, it does! */
  1658.             r->parent = (char *) alloc(size + 1);
  1659.             Fread((genericptr_t) r->parent, 1, size, fd);
  1660.             r->parent[size] = 0;
  1661.         } else
  1662.             r->parent = (char *) 0;
  1663.         
  1664.         Fread((genericptr_t) &r->x, 1, sizeof(r->x), fd);
  1665.                     /* x pos on the grid (1-5) */
  1666.         Fread((genericptr_t) &r->y, 1, sizeof(r->y), fd);
  1667.                      /* y pos on the grid (1-5) */
  1668.         Fread((genericptr_t) &r->w, 1, sizeof(r->w), fd);
  1669.                      /* width of the room */
  1670.         Fread((genericptr_t) &r->h, 1, sizeof(r->h), fd);
  1671.                      /* height of the room */
  1672.         Fread((genericptr_t) &r->xalign, 1, sizeof(r->xalign), fd);
  1673.                      /* horizontal alignment */
  1674.         Fread((genericptr_t) &r->yalign, 1, sizeof(r->yalign), fd);
  1675.                      /* vertical alignment */
  1676.         Fread((genericptr_t) &r->rtype, 1, sizeof(r->rtype), fd);
  1677.                      /* type of room (zoo, shop, etc.) */
  1678.         Fread((genericptr_t) &r->chance, 1, sizeof(r->chance), fd);
  1679.                      /* chance of room being special. */
  1680.         Fread((genericptr_t) &r->rlit, 1, sizeof(r->rlit), fd);
  1681.                      /* lit or not ? */
  1682.         Fread((genericptr_t) &r->filled, 1, sizeof(r->filled), fd);
  1683.                      /* to be filled? */
  1684.         r->nsubroom= 0;
  1685.  
  1686.         /* read the doors */
  1687.         Fread((genericptr_t) &r->ndoor, 1, sizeof(r->ndoor), fd);
  1688.         if ((n = r->ndoor) != 0)
  1689.             r->doors = NewTab(room_door, n);
  1690.         while(n--) {
  1691.             r->doors[n] = New(room_door);
  1692.             Fread((genericptr_t) r->doors[n], 1,
  1693.                 sizeof(room_door), fd);
  1694.         }
  1695.  
  1696.         /* read the traps */
  1697.         Fread((genericptr_t) &r->ntrap, 1, sizeof(r->ntrap), fd);
  1698.         if ((n = r->ntrap) != 0)
  1699.             r->traps = NewTab(trap, n);
  1700.         while(n--) {
  1701.             r->traps[n] = New(trap);
  1702.             Fread((genericptr_t) r->traps[n], 1, sizeof(trap), fd);
  1703.         }
  1704.  
  1705.         /* read the monsters */
  1706.         Fread((genericptr_t) &r->nmonster, 1, sizeof(r->nmonster), fd);
  1707.         if ((n = r->nmonster) != 0)
  1708.             r->monsters = NewTab(monster, n);
  1709.         while(n--) {
  1710.             r->monsters[n] = New(monster);
  1711.             Fread((genericptr_t) r->monsters[n], 1,
  1712.                 sizeof(monster), fd);
  1713.             Fread((genericptr_t) &size, sizeof(size), 1, fd);
  1714.             if (size) {
  1715.                 r->monsters[n]->name= (char *) alloc(size + 1);
  1716.                 Fread((genericptr_t)r->monsters[n]->name,
  1717.                     1, size, fd);
  1718.                 r->monsters[n]->name[size] = 0;
  1719.             } else
  1720.                 r->monsters[n]->name = (char *) 0;
  1721.  
  1722.             Fread((genericptr_t) &size, sizeof(size), 1, fd);
  1723.             if (size) {
  1724.                 r->monsters[n]->appear_as=
  1725.                             (char *) alloc(size + 1);
  1726.                 Fread((genericptr_t)r->monsters[n]->appear_as,
  1727.                     1, size, fd);
  1728.                 r->monsters[n]->appear_as[size] = 0;
  1729.             } else
  1730.                 r->monsters[n]->appear_as = (char *) 0;
  1731.          }
  1732.  
  1733.         /* read the objects */
  1734.         Fread((genericptr_t) &r->nobject, 1, sizeof(r->nobject), fd);
  1735.         if ((n = r->nobject) != 0)
  1736.             r->objects = NewTab(object, n);
  1737.         while (n--) {
  1738.             r->objects[n] = New(object);
  1739.             Fread((genericptr_t) r->objects[n], 1,
  1740.                 sizeof(object), fd);
  1741.             Fread((genericptr_t) &size, 1, sizeof(size), fd);
  1742.             if (size) {
  1743.                 r->objects[n]->name = (char *) alloc(size + 1);
  1744.                 Fread((genericptr_t)r->objects[n]->name,
  1745.                     1, size, fd);
  1746.                 r->objects[n]->name[size] = 0;
  1747.             } else
  1748.                 r->objects[n]->name = (char *) 0;
  1749.         }
  1750.  
  1751.         /* read the stairs */
  1752.         Fread((genericptr_t) &r->nstair, 1, sizeof(r->nstair), fd);
  1753.         if ((n = r->nstair) != 0)
  1754.             r->stairs = NewTab(stair, n);
  1755.         while (n--) {
  1756.             r->stairs[n] = New(stair);
  1757.             Fread((genericptr_t) r->stairs[n], 1,
  1758.                 sizeof(stair), fd);
  1759.         }
  1760.  
  1761.         /* read the altars */
  1762.         Fread((genericptr_t) &r->naltar, 1, sizeof(r->naltar), fd);
  1763.         if ((n = r->naltar) != 0)
  1764.             r->altars = NewTab(altar, n);
  1765.         while (n--) {
  1766.             r->altars[n] = New(altar);
  1767.             Fread((genericptr_t) r->altars[n], 1,
  1768.                 sizeof(altar), fd);
  1769.         }
  1770.  
  1771.         /* read the gold piles */
  1772.         Fread((genericptr_t) &r->ngold, 1, sizeof(r->ngold), fd);
  1773.         if ((n = r->ngold) != 0)
  1774.             r->golds = NewTab(gold, n);
  1775.         while (n--) {
  1776.             r->golds[n] = New(gold);
  1777.             Fread((genericptr_t) r->golds[n], 1, sizeof(gold), fd);
  1778.         }
  1779.  
  1780.         /* read the engravings */
  1781.         Fread((genericptr_t) &r->nengraving, 1,
  1782.             sizeof(r->nengraving), fd);
  1783.         if ((n = r->nengraving) != 0)
  1784.             r->engravings = NewTab(engraving,n);
  1785.         while(n--) {
  1786.             r->engravings[n] = New(engraving);
  1787.             Fread((genericptr_t) r->engravings[n],
  1788.                 1, sizeof *r->engravings[n], fd);
  1789.             size = r->engravings[n]->e.length;
  1790.             r->engravings[n]->e.text = (char *) alloc(size+1);
  1791.             Fread((genericptr_t) r->engravings[n]->e.text,
  1792.                 1, size, fd);
  1793.             r->engravings[n]->e.text[size] = '\0';
  1794.         }
  1795.  
  1796.         /* read the fountains */
  1797.         Fread((genericptr_t) &r->nfountain, 1,
  1798.             sizeof(r->nfountain), fd);
  1799.         if ((n = r->nfountain) != 0)
  1800.             r->fountains = NewTab(fountain, n);
  1801.         while (n--) {
  1802.             r->fountains[n] = New(fountain);
  1803.             Fread((genericptr_t) r->fountains[n], 1,
  1804.                 sizeof(fountain), fd);
  1805.         }
  1806.  
  1807.         /* read the sinks */
  1808.         Fread((genericptr_t) &r->nsink, 1, sizeof(r->nsink), fd);
  1809.         if ((n = r->nsink) != 0)
  1810.             r->sinks = NewTab(sink, n);
  1811.         while (n--) {
  1812.             r->sinks[n] = New(sink);
  1813.             Fread((genericptr_t) r->sinks[n], 1, sizeof(sink), fd);
  1814.         }
  1815.  
  1816.         /* read the pools */
  1817.         Fread((genericptr_t) &r->npool, 1, sizeof(r->npool), fd);
  1818.         if ((n = r->npool) != 0)
  1819.             r->pools = NewTab(pool,n);
  1820.         while (n--) {
  1821.             r->pools[n] = New(pool);
  1822.             Fread((genericptr_t) r->pools[n], 1, sizeof(pool), fd);
  1823.         }
  1824.  
  1825.     }
  1826.  
  1827.     /* Now that we have loaded all the rooms, search the
  1828.      * subrooms and create the links.
  1829.      */
  1830.  
  1831.     for (i = 0; i<nrooms; i++)
  1832.         if (tmproom[i]->parent) {
  1833.             /* Search the parent room */
  1834.             for(j=0; j<nrooms; j++)
  1835.             if (tmproom[j]->name && !strcmp(tmproom[j]->name,
  1836.                                tmproom[i]->parent)) {
  1837.                 n = tmproom[j]->nsubroom++;
  1838.                 tmproom[j]->subrooms[(int)n] = tmproom[i];
  1839.                 break;
  1840.             }
  1841.         }
  1842.  
  1843.     /* 
  1844.      * Create the rooms now...
  1845.      */
  1846.  
  1847.     for (i=0; i < nrooms; i++)
  1848.         if(!tmproom[i]->parent)
  1849.         build_room(tmproom[i], (room *) 0);
  1850.  
  1851.     free_rooms(tmproom, nrooms);
  1852.  
  1853.     /* read the corridors */
  1854.  
  1855.     Fread((genericptr_t) &ncorr, sizeof(ncorr), 1, fd);
  1856.     for (i=0; i<ncorr; i++) {
  1857.         Fread((genericptr_t) &tmpcor, 1, sizeof(tmpcor), fd);
  1858.         create_corridor(&tmpcor);
  1859.     }
  1860.  
  1861.     return TRUE;
  1862. }
  1863.  
  1864. /*
  1865.  * Select a random coordinate in the maze.
  1866.  *
  1867.  * We want a place not 'touched' by the loader.  That is, a place in
  1868.  * the maze outside every part of the special level.
  1869.  */
  1870.  
  1871. static void
  1872. maze1xy(m)
  1873. coord *m;
  1874. {
  1875.     do {
  1876.         m->x = rn1(x_maze_max - 3, 3);
  1877.         m->y = rn1(y_maze_max - 3, 3);
  1878.     } while (!(m->x % 2) || !(m->y % 2) || Map[m->x][m->y]);
  1879. }
  1880.  
  1881. /* 
  1882.  * The Big Thing: special maze loader
  1883.  *
  1884.  * Could be cleaner, but it works.
  1885.  */
  1886.  
  1887. static boolean
  1888. load_maze(fd)
  1889. FILE *fd;
  1890. {
  1891.     xchar   x, y, typ;
  1892.     boolean prefilled;
  1893.  
  1894.     char    n, numpart = 0;
  1895.     xchar   nwalk = 0, nwalk_sav;
  1896.     short   filling;
  1897.     char    halign, valign;
  1898.  
  1899.     int     xi, yi, dir;
  1900.     coord   mm;
  1901.     int     mapcount, mapcountmax, mapfact;
  1902.  
  1903.     lev_region  tmplregion;
  1904.     region  tmpregion;
  1905.     door    tmpdoor;
  1906.     trap    tmptrap;
  1907.     monster tmpmons;
  1908.     object  tmpobj;
  1909.     drawbridge tmpdb;
  1910.     walk    tmpwalk;
  1911.     digpos  tmpdig;
  1912.     lad     tmplad;
  1913.     stair   tmpstair, prevstair;
  1914.     altar   tmpaltar;
  1915.     gold    tmpgold;
  1916.     fountain tmpfountain;
  1917.     engraving tmpengraving;
  1918.     xchar   mustfill[(MAXNROFROOMS+1)*2];
  1919.     struct trap *badtrap;
  1920.     boolean has_bounds;
  1921.  
  1922.     load_common_data(fd, SP_LEV_MAZE);
  1923.  
  1924.     /* Initialize map */
  1925.     Fread((genericptr_t) &filling, 1, sizeof(filling), fd);
  1926.     if(!init_lev.init_present) /* don't init if mkmap() has been called */
  1927.       for(x = 2; x <= x_maze_max; x++)
  1928.     for(y = 0; y <= y_maze_max; y++)
  1929.         if (filling == -1) {
  1930. #ifndef WALLIFIED_MAZE
  1931.             levl[x][y].typ = STONE;
  1932. #else
  1933.             levl[x][y].typ =
  1934.             (y < 2 || ((x % 2) && (y % 2))) ? STONE : HWALL;
  1935. #endif
  1936.             Map[x][y] = 0;
  1937.         } else {
  1938.             levl[x][y].typ = filling;
  1939.             Map[x][y] = 0;
  1940.         }
  1941.  
  1942.     /* Start reading the file */
  1943.     Fread((genericptr_t) &numpart, 1, sizeof(numpart), fd);
  1944.                         /* Number of parts */
  1945.     if (!numpart || numpart > 9)
  1946.     panic("load_maze error: numpart = %d", (int) numpart);
  1947.  
  1948.     while (numpart--) {
  1949.     Fread((genericptr_t) &halign, 1, sizeof(halign), fd);
  1950.                     /* Horizontal alignment */
  1951.     Fread((genericptr_t) &valign, 1, sizeof(valign), fd);
  1952.                     /* Vertical alignment */
  1953.     Fread((genericptr_t) &xsize, 1, sizeof(xsize), fd);
  1954.                     /* size in X */
  1955.     Fread((genericptr_t) &ysize, 1, sizeof(ysize), fd);
  1956.                     /* size in Y */
  1957.     switch((int) halign) {
  1958.         case LEFT:        xstart = 3;                 break;
  1959.         case H_LEFT:    xstart = 2+((x_maze_max-2-xsize)/4);    break;
  1960.         case CENTER:    xstart = 2+((x_maze_max-2-xsize)/2);    break;
  1961.         case H_RIGHT:   xstart = 2+((x_maze_max-2-xsize)*3/4);    break;
  1962.         case RIGHT:     xstart = x_maze_max-xsize-1;        break;
  1963.     }
  1964.     switch((int) valign) {
  1965.         case TOP:        ystart = 3;                 break;
  1966.         case CENTER:    ystart = 2+((y_maze_max-2-ysize)/2);    break;
  1967.         case BOTTOM:    ystart = y_maze_max-ysize-1;        break;
  1968.     }
  1969.     if (!(xstart % 2)) xstart++;
  1970.     if (!(ystart % 2)) ystart++;
  1971.     if ((ystart < 0) || (ystart + ysize > ROWNO)) {
  1972.         /* try to move the start a bit */
  1973.         ystart += (ystart > 0) ? -2 : 2;
  1974.         if(ysize == ROWNO) ystart = 0;
  1975.         if(ystart < 0 || ystart + ysize > ROWNO)
  1976.         panic("reading special level with ysize to large");
  1977.     }
  1978.  
  1979.     /*
  1980.      * If any CROSSWALLs are found, must change to ROOM after REGION's
  1981.      * are laid out.  CROSSWALLS are used to specify "invisible"
  1982.      * boundaries where DOOR syms look bad or aren't desirable.
  1983.      */
  1984.     has_bounds = FALSE;
  1985.  
  1986.     if(init_lev.init_present && xsize <= 1 && ysize <= 1) {
  1987.         xstart = 1;
  1988.         ystart = 0;
  1989.         xsize = COLNO-1;
  1990.         ysize = ROWNO;
  1991.     } else {
  1992.         /* Load the map */
  1993.         for(y = ystart; y < ystart+ysize; y++)
  1994.         for(x = xstart; x < xstart+xsize; x++) {
  1995.             levl[x][y].typ = (schar) fgetc(fd);
  1996.             levl[x][y].lit = FALSE;
  1997.             /*
  1998.              * Note: Even though levl[x][y].typ is type schar,
  1999.              *     lev_comp.y saves it as type char. Since schar != char
  2000.              *     all the time we must make this exception or hack
  2001.              *     through lev_comp.y to fix.
  2002.              */
  2003.  
  2004.             /*
  2005.              *  Set secret doors to closed (why not trapped too?).  Set
  2006.              *  the horizontal bit.
  2007.              */
  2008.             if (levl[x][y].typ == SDOOR || IS_DOOR(levl[x][y].typ)) {
  2009.             if(levl[x][y].typ == SDOOR)
  2010.                 levl[x][y].doormask = D_CLOSED;
  2011.             /*
  2012.              *  If there is a wall to the left that connects to a
  2013.              *  (secret) door, then it is horizontal.  This does
  2014.              *  not allow (secret) doors to be corners of rooms.
  2015.              */
  2016.             if (x != xstart && (IS_WALL(levl[x-1][y].typ) ||
  2017.                         levl[x-1][y].horizontal))
  2018.                 levl[x][y].horizontal = 1;
  2019.             } else if(levl[x][y].typ == HWALL)
  2020.             levl[x][y].horizontal = 1;
  2021.             else if(levl[x][y].typ == LAVAPOOL)
  2022.             levl[x][y].lit = 1;
  2023.             else if(levl[x][y].typ == CROSSWALL)
  2024.             has_bounds = TRUE;
  2025.             Map[x][y] = 1;
  2026.         }
  2027.     }
  2028.  
  2029.     Fread((genericptr_t) &n, 1, sizeof(n), fd);
  2030.                         /* Number of level regions */
  2031.     if(n) {
  2032.         if(num_lregions) {
  2033.         /* realloc the lregion space to add the new ones */
  2034.         /* don't really free it up until the whole level is done */
  2035.         lev_region *newl = (lev_region *) alloc(sizeof(lev_region) *
  2036.                             (n+num_lregions));
  2037.         (void) memcpy((genericptr_t)(newl+n), (genericptr_t)lregions,
  2038.                     sizeof(lev_region) * num_lregions);
  2039.         Free(lregions);
  2040.         num_lregions += n;
  2041.         lregions = newl;
  2042.         } else {
  2043.         num_lregions = n;
  2044.         lregions = (lev_region *) alloc(sizeof(lev_region) * n);
  2045.         }
  2046.     }
  2047.  
  2048.     while(n--) {
  2049.         Fread((genericptr_t) &tmplregion, sizeof(tmplregion), 1, fd);
  2050.         if(tmplregion.rname) {
  2051.         char len;
  2052.  
  2053.         Fread((genericptr_t) &len, sizeof(len), 1, fd);
  2054.         tmplregion.rname = (char *) alloc(len + 1);
  2055.         Fread((genericptr_t) tmplregion.rname, len, 1, fd);
  2056.         tmplregion.rname[len] = 0;
  2057.         }
  2058.         if(!tmplregion.in_islev) {
  2059.         get_location(&tmplregion.inarea.x1, &tmplregion.inarea.y1,
  2060.                                 DRY|WET);
  2061.         get_location(&tmplregion.inarea.x2, &tmplregion.inarea.y2,
  2062.                                 DRY|WET);
  2063.         }
  2064.         if(!tmplregion.del_islev) {
  2065.         get_location(&tmplregion.delarea.x1, &tmplregion.delarea.y1,
  2066.                                 DRY|WET);
  2067.         get_location(&tmplregion.delarea.x2, &tmplregion.delarea.y2,
  2068.                                 DRY|WET);
  2069.         }
  2070.         lregions[n] = tmplregion;
  2071.     }
  2072.  
  2073.     Fread((genericptr_t) &n, 1, sizeof(n), fd);
  2074.                         /* Random objects */
  2075.     if(n) {
  2076.         Fread((genericptr_t)robjects, sizeof(*robjects), (int) n, fd);
  2077.         sp_lev_shuffle(robjects, (char *)0, (int)n);
  2078.     }
  2079.  
  2080.     Fread((genericptr_t) &n, 1, sizeof(n), fd);
  2081.                         /* Random locations */
  2082.     if(n) {
  2083.         Fread((genericptr_t)rloc_x, sizeof(*rloc_x), (int) n, fd);
  2084.         Fread((genericptr_t)rloc_y, sizeof(*rloc_y), (int) n, fd);
  2085.         sp_lev_shuffle(rloc_x, rloc_y, (int)n);
  2086.     }
  2087.  
  2088.     Fread((genericptr_t) &n, 1, sizeof(n), fd);
  2089.                         /* Random monsters */
  2090.     if(n) {
  2091.         Fread((genericptr_t)rmonst, sizeof(*rmonst), (int) n, fd);
  2092.         sp_lev_shuffle(rmonst, (char *)0, (int)n);
  2093.     }
  2094.  
  2095.     Fread((genericptr_t) &n, 1, sizeof(n), fd);
  2096.                         /* Number of subrooms */
  2097.  
  2098.     (void) memset((genericptr_t)mustfill, 0, sizeof(mustfill));
  2099.  
  2100.     while(n--) {
  2101.         register struct mkroom *troom;
  2102.  
  2103.         Fread((genericptr_t)&tmpregion, 1, sizeof(tmpregion), fd);
  2104.  
  2105.         if(tmpregion.rtype > MAXRTYPE) {
  2106.             tmpregion.rtype -= MAXRTYPE+1;
  2107.             prefilled = TRUE;
  2108.         } else
  2109.             prefilled = FALSE;
  2110.  
  2111.         if(tmpregion.rlit < 0)
  2112.             tmpregion.rlit = (rnd(1+abs(depth(&u.uz))) < 11 && rn2(77))
  2113.             ? TRUE : FALSE;
  2114.  
  2115.         get_location(&tmpregion.x1, &tmpregion.y1, DRY|WET);
  2116.         get_location(&tmpregion.x2, &tmpregion.y2, DRY|WET);
  2117.  
  2118.         if (((tmpregion.rtype == OROOM) && !tmpregion.rirreg) ||
  2119.             (nroom >= MAXNROFROOMS)) {
  2120.             if(tmpregion.rtype != OROOM || tmpregion.rirreg)
  2121.             impossible("Too many rooms on new level!");
  2122.             light_region(&tmpregion);
  2123.             continue;
  2124.         }
  2125.  
  2126.         troom = &rooms[nroom];
  2127.  
  2128.         /* mark rooms that must be filled, but do it later */
  2129.         if (tmpregion.rtype != OROOM)
  2130.             mustfill[nroom] = (prefilled ? 2 : 1);
  2131.  
  2132.         if(tmpregion.rirreg) {
  2133.             min_rx = max_rx = tmpregion.x1;
  2134.             min_ry = max_ry = tmpregion.y1;
  2135.             flood_fill_rm(tmpregion.x1, tmpregion.y1,
  2136.                   nroom+ROOMOFFSET, tmpregion.rlit, TRUE);
  2137.             add_room(min_rx, min_ry, max_rx, max_ry,
  2138.                  FALSE, tmpregion.rtype, TRUE);
  2139.             troom->rlit = tmpregion.rlit;
  2140.             troom->irregular = TRUE;
  2141.         } else {
  2142.             add_room(tmpregion.x1, tmpregion.y1,
  2143.                  tmpregion.x2, tmpregion.y2,
  2144.                  tmpregion.rlit, tmpregion.rtype, TRUE);
  2145. #ifdef SPECIALIZATION
  2146.             topologize(troom,FALSE);        /* set roomno */
  2147. #else
  2148.             topologize(troom);            /* set roomno */
  2149. #endif
  2150.         }
  2151.     }
  2152.  
  2153.     Fread((genericptr_t) &n, 1, sizeof(n), fd);
  2154.                         /* Number of doors */
  2155.     while(n--) {
  2156.         struct mkroom *croom = &rooms[0];
  2157.  
  2158.         Fread((genericptr_t)&tmpdoor, 1, sizeof(tmpdoor), fd);
  2159.  
  2160.         x = tmpdoor.x;    y = tmpdoor.y;
  2161.         typ = tmpdoor.mask == -1 ? rnddoor() : tmpdoor.mask;
  2162.  
  2163.         get_location(&x, &y, DRY);
  2164.         if(levl[x][y].typ != SDOOR)
  2165.             levl[x][y].typ = DOOR;
  2166.         else {
  2167.             if(typ < D_CLOSED)
  2168.                 typ = D_CLOSED; /* force it to be closed */
  2169.         }
  2170.         levl[x][y].doormask = typ;
  2171.  
  2172.         /* Now the complicated part, list it with each subroom */
  2173.         /* The dog move and mail daemon routines use this */
  2174.         while(croom->hx >= 0 && doorindex < DOORMAX) {
  2175.             if(croom->hx >= x-1 && croom->lx <= x+1 &&
  2176.                croom->hy >= y-1 && croom->ly <= y+1) {
  2177.             /* Found it */
  2178.             add_door(x, y, croom);
  2179.             }
  2180.             croom++;
  2181.         }
  2182.     }
  2183.  
  2184.     /* now that we have rooms _and_ associated doors, fill the rooms */
  2185.     for(n = 0; n < SIZE(mustfill); n++)
  2186.         if(mustfill[(int)n])
  2187.         fill_room(&rooms[(int)n], (mustfill[(int)n] == 2));
  2188.  
  2189.     /* if special boundary syms (CROSSWALL) in map, remove them now */
  2190.     if(has_bounds) {
  2191.         for(x = xstart; x < xstart+xsize; x++)
  2192.         for(y = ystart; y < ystart+ysize; y++)
  2193.             if(levl[x][y].typ == CROSSWALL)
  2194.             levl[x][y].typ = ROOM;
  2195.     }
  2196.  
  2197.     Fread((genericptr_t) &n, 1, sizeof(n), fd);
  2198.                         /* Number of traps */
  2199.     while(n--) {
  2200.         Fread((genericptr_t)&tmptrap, 1, sizeof(tmptrap), fd);
  2201.  
  2202.         create_trap(&tmptrap, (struct mkroom *)0);
  2203.     }
  2204.  
  2205.     Fread((genericptr_t) &n, 1, sizeof(n), fd);
  2206.                         /* Number of monsters */
  2207.     while(n--) {
  2208.         short size;
  2209.  
  2210.         Fread((genericptr_t) &tmpmons, 1, sizeof(tmpmons), fd);
  2211.         Fread((genericptr_t) &size, 1, sizeof(size), fd);
  2212.         if (size) {
  2213.             tmpmons.name = (char *) alloc(size + 1);
  2214.             Fread((genericptr_t) tmpmons.name, 1, size, fd);
  2215.             tmpmons.name[size] = 0;
  2216.         } else
  2217.             tmpmons.name = (char *) 0;
  2218.         Fread((genericptr_t) &size, 1, sizeof(size), fd);
  2219.         if (size) {
  2220.             tmpmons.appear_as = (char *) alloc(size + 1);
  2221.             Fread((genericptr_t) tmpmons.appear_as, 1, size, fd);
  2222.             tmpmons.appear_as[size] = 0;
  2223.         } else
  2224.             tmpmons.appear_as = (char *) 0;
  2225.  
  2226.         create_monster(&tmpmons, (struct mkroom *)0);
  2227.  
  2228.         if (tmpmons.name)
  2229.             free((genericptr_t) tmpmons.name);
  2230.         if (tmpmons.appear_as)
  2231.             free((genericptr_t) tmpmons.appear_as);
  2232.     }
  2233.  
  2234.     Fread((genericptr_t) &n, 1, sizeof(n), fd);
  2235.                         /* Number of objects */
  2236.     while(n--) {
  2237.         short size;
  2238.  
  2239.         Fread((genericptr_t) &tmpobj, 1, sizeof(object), fd);
  2240.         Fread((genericptr_t) &size, 1, sizeof(size), fd);
  2241.         if (size) {
  2242.             tmpobj.name = (char *) alloc(size + 1);
  2243.             Fread((genericptr_t) tmpobj.name, 1, size, fd);
  2244.             tmpobj.name[size] = 0;
  2245.         } else
  2246.             tmpobj.name = (char *) 0;
  2247.  
  2248.         create_object(&tmpobj, (struct mkroom *)0);
  2249.  
  2250.         if (size)
  2251.             free((genericptr_t) tmpobj.name);
  2252.     }
  2253.  
  2254.     Fread((genericptr_t) &n, 1, sizeof(n), fd);
  2255.                         /* Number of drawbridges */
  2256.     while(n--) {
  2257.         Fread((genericptr_t)&tmpdb, 1, sizeof(tmpdb), fd);
  2258.  
  2259.         x = tmpdb.x;  y = tmpdb.y;
  2260.         get_location(&x, &y, DRY|WET);
  2261.  
  2262.         if (!create_drawbridge(x, y, tmpdb.dir, tmpdb.db_open))
  2263.             impossible("Cannot create drawbridge.");
  2264.     }
  2265.  
  2266.     Fread((genericptr_t) &n, 1, sizeof(n), fd);
  2267.                         /* Number of mazewalks */
  2268.     while(n--) {
  2269.         Fread((genericptr_t)&tmpwalk, 1, sizeof(tmpwalk), fd);
  2270.  
  2271.         get_location(&tmpwalk.x, &tmpwalk.y, DRY|WET);
  2272.  
  2273.         walklist[nwalk++] = tmpwalk;
  2274.     }
  2275.  
  2276.     Fread((genericptr_t) &n, 1, sizeof(n), fd);
  2277.                         /* Number of non_diggables */
  2278.     while(n--) {
  2279.         Fread((genericptr_t)&tmpdig, 1, sizeof(tmpdig), fd);
  2280.  
  2281.         get_location(&tmpdig.x1, &tmpdig.y1, DRY|WET);
  2282.         get_location(&tmpdig.x2, &tmpdig.y2, DRY|WET);
  2283.  
  2284.         set_wall_property(tmpdig.x1, tmpdig.y1,
  2285.                   tmpdig.x2, tmpdig.y2, W_NONDIGGABLE);
  2286.     }
  2287.  
  2288.     Fread((genericptr_t) &n, 1, sizeof(n), fd);
  2289.                         /* Number of non_passables */
  2290.     while(n--) {
  2291.         Fread((genericptr_t)&tmpdig, 1, sizeof(tmpdig), fd);
  2292.  
  2293.         get_location(&tmpdig.x1, &tmpdig.y1, DRY|WET);
  2294.         get_location(&tmpdig.x2, &tmpdig.y2, DRY|WET);
  2295.  
  2296.         set_wall_property(tmpdig.x1, tmpdig.y1,
  2297.                   tmpdig.x2, tmpdig.y2, W_NONPASSWALL);
  2298.     }
  2299.  
  2300.     Fread((genericptr_t) &n, 1, sizeof(n), fd);
  2301.                         /* Number of ladders */
  2302.     while(n--) {
  2303.         Fread((genericptr_t)&tmplad, 1, sizeof(tmplad), fd);
  2304.  
  2305.         x = tmplad.x;  y = tmplad.y;
  2306.         get_location(&x, &y, DRY);
  2307.  
  2308.         levl[x][y].typ = LADDER;
  2309.         if (tmplad.up == 1) {
  2310.             xupladder = x;    yupladder = y;
  2311.             levl[x][y].ladder = LA_UP;
  2312.         } else {
  2313.             xdnladder = x;    ydnladder = y;
  2314.             levl[x][y].ladder = LA_DOWN;
  2315.         }
  2316.     }
  2317.  
  2318.     prevstair.x = prevstair.y = 0;
  2319.     Fread((genericptr_t) &n, 1, sizeof(n), fd);
  2320.                         /* Number of stairs */
  2321.     while(n--) {
  2322.         Fread((genericptr_t)&tmpstair, 1, sizeof(tmpstair), fd);
  2323.  
  2324.         xi = 0;
  2325.         do {
  2326.             x = tmpstair.x;  y = tmpstair.y;
  2327.             get_location(&x, &y, DRY);
  2328.         } while(prevstair.x && xi++ < 100 &&
  2329.             distmin(x,y,prevstair.x,prevstair.y) <= 8);
  2330.         if ((badtrap = t_at(x,y)) != 0) deltrap(badtrap);
  2331.         mkstairs(x, y, (char)tmpstair.up, (struct mkroom *)0);
  2332.         prevstair.x = x;
  2333.         prevstair.y = y;
  2334.     }
  2335.  
  2336.     Fread((genericptr_t) &n, 1, sizeof(n), fd);
  2337.                         /* Number of altars */
  2338.     while(n--) {
  2339.         Fread((genericptr_t)&tmpaltar, 1, sizeof(tmpaltar), fd);
  2340.  
  2341.         create_altar(&tmpaltar, (struct mkroom *)0);
  2342.     }
  2343.  
  2344.     Fread((genericptr_t) &n, 1, sizeof(n), fd);
  2345.                         /* Number of gold pile */
  2346.     while (n--) {
  2347.         Fread((genericptr_t)&tmpgold, 1, sizeof(tmpgold), fd);
  2348.  
  2349.         create_gold(&tmpgold, (struct mkroom *)0);
  2350.     }
  2351.  
  2352.     Fread((genericptr_t) &n, 1, sizeof(n), fd);
  2353.                         /* Number of engravings */
  2354.     while(n--) {
  2355.         int size;
  2356.         Fread((genericptr_t) &tmpengraving, 1,
  2357.             sizeof(tmpengraving), fd);
  2358.         size = tmpengraving.e.length;
  2359.         tmpengraving.e.text = (char *) alloc(size+1);
  2360.         Fread((genericptr_t) tmpengraving.e.text, 1, size, fd);
  2361.         tmpengraving.e.text[size] = '\0';
  2362.         
  2363.         x = tmpengraving.x; y = tmpengraving.y;
  2364.         get_location(&x, &y, DRY);
  2365.         make_engr_at(x, y, tmpengraving.e.text, 0L, tmpengraving.etype);
  2366.         free((genericptr_t) tmpengraving.e.text);
  2367.     }
  2368.  
  2369.     Fread((genericptr_t) &n, 1, sizeof(n), fd);
  2370.                         /* Number of fountains */
  2371.     while (n--) {
  2372.         Fread((genericptr_t)&tmpfountain, 1, sizeof(tmpfountain), fd);
  2373.  
  2374.         create_feature(tmpfountain.x, tmpfountain.y,
  2375.                    (struct mkroom *)0, FOUNTAIN);
  2376.     }
  2377.     }
  2378.  
  2379.     nwalk_sav = nwalk;
  2380.     while(nwalk--) {
  2381.         xi = walklist[nwalk].x;
  2382.         yi = walklist[nwalk].y;
  2383.         dir = walklist[nwalk].dir;
  2384.  
  2385.         move(&xi, &yi, dir);
  2386.         x = xi;
  2387.         y = yi;
  2388.  
  2389.         if(!IS_DOOR(levl[x][y].typ)) {
  2390. #ifndef WALLIFIED_MAZE
  2391.         levl[x][y].typ = CORR;
  2392. #else
  2393.         levl[x][y].typ = ROOM;
  2394. #endif
  2395.         levl[x][y].flags = 0;
  2396.         }
  2397.  
  2398.         /*
  2399.          * We must be sure that the parity of the coordinates for
  2400.          * walkfrom() is odd.  But we must also take into account
  2401.          * what direction was chosen.
  2402.          */
  2403.         if(!(x % 2)) {
  2404.         if (dir == W_EAST)
  2405.             x++;
  2406.         else
  2407.             x--;
  2408.  
  2409.         /* no need for IS_DOOR check; out of map bounds */
  2410. #ifndef WALLIFIED_MAZE
  2411.         levl[x][y].typ = CORR;
  2412. #else
  2413.         levl[x][y].typ = ROOM;
  2414. #endif
  2415.         levl[x][y].flags = 0;
  2416.         }
  2417.  
  2418.         if (!(y % 2))
  2419.         if (dir == W_SOUTH)
  2420.             y++;
  2421.         else
  2422.             y--;
  2423.  
  2424.         walkfrom(x, y);
  2425.     }
  2426.     wallification(1, 0, COLNO-1, ROWNO-1);
  2427.  
  2428.     /*
  2429.      * If there's a significant portion of maze unused by the special level,
  2430.      * we don't want it empty.
  2431.      *
  2432.      * Makes the number of traps, monsters, etc. proportional
  2433.      * to the size of the maze.
  2434.      */
  2435.     mapcountmax = mapcount = (x_maze_max - 2) * (y_maze_max - 2);
  2436.  
  2437.     for(x = 2; x < x_maze_max; x++)
  2438.     for(y = 0; y < y_maze_max; y++)
  2439.         if(Map[x][y]) mapcount--;
  2440.  
  2441.     if (nwalk_sav && (mapcount > (int) (mapcountmax / 10))) {
  2442.         mapfact = (int) ((mapcount * 100L) / mapcountmax);
  2443.         for(x = rnd((int) (20 * mapfact) / 100); x; x--) {
  2444.             maze1xy(&mm);
  2445.             (void) mkobj_at(rn2(2) ? GEM_CLASS : RANDOM_CLASS,
  2446.                             mm.x, mm.y, TRUE);
  2447.         }
  2448.         for(x = rnd((int) (12 * mapfact) / 100); x; x--) {
  2449.             maze1xy(&mm);
  2450.             (void) mksobj_at(BOULDER, mm.x, mm.y, TRUE);
  2451.         }
  2452.         maze1xy(&mm);
  2453.         (void) makemon(&mons[PM_MINOTAUR], mm.x, mm.y);
  2454.         for(x = rnd((int) (12 * mapfact) / 100); x; x--) {
  2455.             maze1xy(&mm);
  2456.             (void) makemon((struct permonst *) 0, mm.x, mm.y);
  2457.         }
  2458.         for(x = rn2((int) (15 * mapfact) / 100); x; x--) {
  2459.             maze1xy(&mm);
  2460.             mkgold(0L,mm.x,mm.y);
  2461.         }
  2462.         for(x = rn2((int) (15 * mapfact) / 100); x; x--) {
  2463.             int trytrap = rndtrap();
  2464.  
  2465.             maze1xy(&mm);
  2466.             if (is_pool(mm.x,mm.y)) continue;
  2467.             if (sobj_at(BOULDER, mm.x, mm.y))
  2468.             while ((trytrap == PIT) || (trytrap == SPIKED_PIT)) 
  2469.                 trytrap = rndtrap();
  2470.             (void) maketrap(mm.x, mm.y, trytrap);
  2471.         }
  2472.     }
  2473.     return TRUE;
  2474. }
  2475.  
  2476. /*
  2477.  * General loader
  2478.  */
  2479.  
  2480. boolean
  2481. load_special(name)
  2482. const char *name;
  2483. {
  2484.     FILE *fd;
  2485.     boolean result;
  2486.     char c;
  2487.  
  2488.     fd = fopen_datafile(name, RDMODE);
  2489.     if (!fd) return FALSE;
  2490.  
  2491.     Fread((genericptr_t) &c, 1, sizeof(c), fd); /* c Header */
  2492.  
  2493.     switch (c) {
  2494.         case SP_LEV_ROOMS:
  2495.             result = load_rooms(fd);
  2496.             break;
  2497.         case SP_LEV_MAZE:
  2498.             result = load_maze(fd);
  2499.             break;
  2500.         default:    /* ??? */
  2501.             result = FALSE;
  2502.     }
  2503.     (void)fclose(fd);
  2504.     return result;
  2505. }
  2506.  
  2507. /*sp_lev.c*/
  2508.